package cn.gs.serializable.serialize;

// @author gs
import cn.gs.serializable.entity.EntityController;
import cn.gs.serializable.entity.IEntity;
import java.io.*;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SerializeController extends LinkedList<ISerialize> implements ISerialize {

    public SerializeController() {
        addStandardSerialize();
    }

    public SerializeController(ISerialize... link) {
        this.addAll(Arrays.asList(link));
        addStandardSerialize();
    }

    public SerializeController(List<ISerialize> link) {
        this.addAll(link);
        addStandardSerialize();
    }

    private void addStandardSerialize() {
        ISerialize[] ss = new ISerialize[]{new AnnotationObjSerialize(), new NumberSerialize(), new EnumSerialize(), new NullSerialize(), new BooleanSerialize(), new ClassSerialize(), new StringSerialize(), new ArraySerialize(), new SetSerialize(), new CollectionSerialize(), new MapSerialize(), new ObjectSerialize()};
        this.addAll(Arrays.asList(ss));
    }
    private static final SerializeController INSTANCE = new SerializeController();

    public static <T> T staticToObject(String s, Class<T> clazz) {
        return INSTANCE.toObject(s, clazz);
    }

    public <T> T toObject(String s, Class<T> clazz) {
        StringReader sr = new StringReader(s);
        try {
            T t = toObject(sr, clazz);
            return t;
        } catch (IOException ex) {
            Logger.getLogger(SerializeController.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    public <T> T toObject(Reader sr, Class<T> clazz) throws IOException {
        IEntity e = (new EntityController()).read(sr);
        return this.parser(e, clazz);
    }

    public static String staticToString(Object o) {
        return INSTANCE.toString(o);
    }

    public String toString(Object o) {
        StringWriter sw = new StringWriter();
        try {
            toString(o, sw);
        } catch (IOException ex) {
            Logger.getLogger(SerializeController.class.getName()).log(Level.SEVERE, null, ex);
        }
        return sw.toString();
    }

    public void toString(Object o, Writer writer) throws IOException {
        IEntity e = this.convert(o);
        if (e != null) {
            e.write(new EntityController(), writer);
        }
    }

    public <T> T parser(IEntity from, Class<T> clazz) {
        if (Object.class.equals(clazz)) {
            clazz = null;
        }
        for (ISerialize i : this) {
            T t = i.toObj(this, from, clazz);
            if (t != null) {
                return t;
            }
        }
        return null;
    }

    public IEntity convert(Object o) {
        for (ISerialize i : this) {
            IEntity t = i.fromObj(this, o);
            if (t != null) {
                return t;
            }
        }
        return null;
    }

    @Override
    public <T> T toObj(ISerialize ctrl, IEntity from, Class<T> clazz) {
        return this.parser(from, clazz);
    }

    @Override
    public IEntity fromObj(ISerialize ctrl, Object from) {
        return this.convert(from);
    }
}
